package com.ch.mybatis;

import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;

public class TypeResolver {

    /** 封装每层类型信息 */
    public static class TypeInfo {
        /** 原始类型，例如 List、Map、String、User 等 */
        public Type rawType;

        /** 泛型参数（嵌套类型） */
        public List<TypeInfo> generics = new ArrayList<>();

        @Override
        public String toString() {
            if (generics.isEmpty()) {
                return rawType.getTypeName();
            }
            StringJoiner joiner = new StringJoiner(", ");
            for (TypeInfo t : generics) {
                joiner.add(t.toString());
            }
            return rawType.getTypeName() + "<" + joiner + ">";
        }
    }

    /**
     * 解析任意类型（支持递归嵌套）
     */
    public static TypeInfo resolveType(Type type) {
        TypeInfo info = new TypeInfo();

        if (type instanceof ParameterizedType pt) {
            info.rawType = pt.getRawType();
            for (Type arg : pt.getActualTypeArguments()) {
                info.generics.add(resolveType(arg)); // 递归处理泛型参数
            }
        } else if (type instanceof WildcardType wt) {
            // 通配符 ? extends Number / ? super String
            info.rawType = wt;
            for (Type upper : wt.getUpperBounds()) {
                info.generics.add(resolveType(upper));
            }
        } else if (type instanceof TypeVariable<?> tv) {
            // 泛型变量 T 等
            info.rawType = tv;
            for (Type bound : tv.getBounds()) {
                info.generics.add(resolveType(bound));
            }
        } else {
            // 普通类型，如 String、Integer、User
            info.rawType = type;
        }

        return info;
    }

    /**
     * 打印指定类某个方法的返回值类型结构
     */
    public static void printMethodReturnType(Class<?> clazz, String methodName) {
        try {
            Method method = clazz.getMethod(methodName);
            Type returnType = method.getGenericReturnType();
            TypeInfo info = resolveType(returnType);
            System.out.println("返回值类型结构： " + info);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}
